﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using FinPlusCommon;

namespace FinPlusComponents
{
    public class FinPlusQuoteSpread : FinPlusComponent
    {
        public string Instrument { get; private set; }
        public string SpreadTo { get; private set; }
        public string SpreadType { get; private set; }
        public double Weight { get; private set; }
        public bool IsMktToMkt { get; private set; }
        public bool IsReadyBuy { get; private set; }
        public bool IsReadySell { get; private set; }
        public PropertyChangedEventHandler SpreadChanged;

        private enum Params { Instrument, Spread, IsMktToMkt, SpreadType, Weight, SpreadName, Trader, BuyAdj, SellAdj, Buy, Sell }
        private IFunction _instrument;

        //extra fields
        private readonly IItem _spreadTo, _buyAdj, _sellAdj, _spreadType, _isMktToMkt;

        //construct
        public FinPlusQuoteSpread(IFunction instrument, IFunction spread)
        {
            _instrument = instrument;
            Instrument = instrument[Params.Instrument.ToString()].ToString();
            SpreadTo = spread[Params.Spread.ToString()].ToString();
            IsMktToMkt = (bool)spread.Value(Params.IsMktToMkt.ToString());
            SpreadType = spread[Params.SpreadType.ToString()].ToString();
            Weight = (double)spread.Value(Params.Weight.ToString());

            var spreadName = spread[Params.SpreadName.ToString()].ToString();
            var spreadType = spread.Value(Params.SpreadType.ToString());
            var spreadTo = spread[Params.Spread.ToString()].ToString();
            var traderName = spread[Params.Trader.ToString()].ToString();

            _spreadTo = _instrument.Add(Params.Spread.ToString() + spreadName, spreadTo, traderName);
            _buyAdj = _instrument.Add(Params.BuyAdj.ToString() + spreadName, spread.Value(Params.BuyAdj.ToString()), traderName);
            _sellAdj = _instrument.Add(Params.SellAdj.ToString() + spreadName, spread.Value(Params.SellAdj.ToString()), traderName);
            _spreadType = _instrument.Add(Params.SpreadType.ToString() + spreadName, spreadType, traderName);
            _isMktToMkt = _instrument.Add(Params.IsMktToMkt.ToString() + spreadName, spread.Value(Params.IsMktToMkt.ToString()), traderName);

            _spreadTo.PropertyChanged += Spread_Changed;
            _buyAdj.PropertyChanged += Spread_Changed;
            _sellAdj.PropertyChanged += Spread_Changed;
            _spreadType.PropertyChanged += Spread_Changed;
            _isMktToMkt.PropertyChanged += Spread_Changed;

            IsValid = true;
        }

        //public
        public double Adjustment(string buySell)
        {
            if (buySell.Equals(Params.Buy.ToString()))
            {
                IsReadyBuy = true;
                return (double)_buyAdj.Object;
            }
            else if (buySell.Equals(Params.Sell.ToString()))
            {
                IsReadySell = true;
                return (double)_sellAdj.Object;
            }
            else
                throw new Exception(string.Format("error in {0} for spread to {1}", Instrument, SpreadTo));
        }

        //events
        private void Spread_Changed(object s, PropertyChangedEventArgs a)
        {
            if (SpreadChanged != null)
                SpreadChanged.Invoke(s, a);
        }
    }

    public class FinPlusQuoteSpreadCallbacks : ConcurrentDictionary<string, Action<string, FinPlusQuoteWrapper, string>> { }

    public class FinPlusQuoteSpreads : ConcurrentDictionary<string, FinPlusQuoteSpread>
    {
        public FinPlusQuoteSpreads() { }

        public bool IsReady()
        {
            foreach (var spread in this.Values)
                if (!string.IsNullOrEmpty(spread.SpreadTo))
                    if (!spread.IsReadyBuy || !spread.IsReadySell)
                        return false;

            return true;
        }
    }

}
